package blazingbubble.gui.panels;


import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.SocketException;

import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.SliderUI;

import spark.network.Sender;
import spark.network.ServerConnection;
import spark.network.SessionFactory;

import moltencore.config.Config;
import moltencore.config.ConfigReader;
import moltencore.config.exception.ConfigReaderException;
import moltencore.game.Game;
import moltencore.game.GameDeathmatch;
import moltencore.game.GameShootEmUp;
import moltencore.game.GameTimeattack;
import moltencore.game.Settings;
import moltencore.game.Game.Mode;
import moltencore.game.loader.GameCreator;
import moltencore.game.loader.exception.FieldCreationException;
import moltencore.game.loader.exception.GameCreationException;
import moltencore.network.game.GameDemon;
import moltencore.network.game.GameLobby;
import moltencore.network.serverlobby.exception.LobbyCreationException;

import blazingbubble.game.ILobbyGameEventListener;
import blazingbubble.game.command.net.NetGameCommandFactory;
import blazingbubble.gui.BlazingBubble;
import blazingbubble.gui.INavigationButton;
import blazingbubble.gui.ISwitchable;
import blazingbubble.gui.PanelRegistry;
import blazingbubble.gui.Resources;
import blazingbubble.gui.elements.MenuButton;
import blazingbubble.gui.elements.MenuComboBox;
import blazingbubble.gui.elements.MenuLabel;
import blazingbubble.gui.elements.MenuTextField;

public class HostGameDefaultOptionsPanel extends JPanel implements ChangeListener, ActionListener{
	private static final long serialVersionUID = -8832547985280683404L;

	public static final String PANEL_NAME = "HostGameDefaultOptions";
	
	private static final Image BACKGROUND_IMAGE = Toolkit.getDefaultToolkit().createImage(Resources.BACKGROUND_NOTITLE_IMAGEPATH);
	
	private static final String GAMENAMELABEL_TEXT = "Game Name:";
	private static final String GAMETYPELABEL_TEXT = "Game Type:";
	private static final String MAXPLAYERSLABEL_TEXT = "Max. Players:";
	private static final String REMOTEGAMELABEL_TEXT = "Remote Game:";
	
	private ISwitchable parentFrame = null;
	
	private ILobbyGameEventListener lobbyGameEventListener = null;

	private MenuLabel gameNameLabel = new MenuLabel(GAMENAMELABEL_TEXT, Font.BOLD, 12);
	private MenuTextField gameNameTextField = new MenuTextField(Resources.TEXTFIELD_WIDE_BORDERS_IMAGEPATH, 25, Font.PLAIN, 20);
	
	private MenuLabel gameTypeLabel = new MenuLabel(GAMETYPELABEL_TEXT, Font.BOLD, 12);
	private MenuComboBox gameTypeComboBox = new MenuComboBox(Font.PLAIN, 12);
	
	private MenuLabel maxPlayersLabel = new MenuLabel(MAXPLAYERSLABEL_TEXT, Font.BOLD, 12);
	private MenuTextField maxPlayersSelectedField = new MenuTextField(Resources.TEXTFIELD_SMALL_IMAGEPATH, 1, Font.PLAIN, 12);
	private JSlider maxPlayersSlider = new JSlider(2, 5);
	
	private MenuButton expandButton = new MenuButton(Resources.EXPANDBUTTON_IMAGEPATH);
	private MenuButton collapseButton = new MenuButton(Resources.COLLAPSEBUTTON_IMAGEPATH);
	
	private MenuButton startButton = new MenuButton(Resources.STARTGAMEBUTTON_IMAGEPATH);
	private MenuButton backButton = new MenuButton(Resources.BACKBUTTON_SMALL_IMAGEPATH);
	
	private MenuLabel remoteGameLabel = new MenuLabel(REMOTEGAMELABEL_TEXT, Font.BOLD, 12);
	private JCheckBox remoteGameBox = new JCheckBox();
	
	private HostGameCustomOptionsPanel customOptionsPanel = new HostGameCustomOptionsPanel();

	public HostGameDefaultOptionsPanel(ISwitchable parentFrame){
		this.parentFrame = parentFrame;
		PanelRegistry.getInstance().registerPanel(PANEL_NAME, this);
		setUp();
	}

	private void setUp(){
		this.setSize(350, 450);
		this.setLayout(null);
		
		this.add(gameNameLabel);
		gameNameLabel.setBounds(5, 5, 335, 25);
		
		this.add(gameNameTextField);
		gameNameTextField.setBounds(5, 30, 335, 35);
		
		this.add(gameTypeLabel);
		gameTypeLabel.setBounds(5, 65, 335, 25);
		
		gameTypeComboBox.addItem(Mode.DeathMatch);
		gameTypeComboBox.addItem(Mode.ShootEmUp);
		gameTypeComboBox.addItem(Mode.TimeAttack);
		this.add(gameTypeComboBox);
		gameTypeComboBox.setBounds(5, 80, 335, 35);
		
		this.add(maxPlayersLabel);
		maxPlayersLabel.setBounds(5, 105, 335, 25);
		
		this.add(maxPlayersSelectedField);
		maxPlayersSelectedField.setHorizontalAlignment(MenuLabel.CENTER);
		maxPlayersSelectedField.setBounds(5, 130, 25, 35);
		maxPlayersSelectedField.setEditable(false);
		maxPlayersSelectedField.setText(Integer.toString(maxPlayersSlider.getValue()));
		
		maxPlayersSlider.setMinorTickSpacing(1);
		maxPlayersSlider.setPaintTicks(true);
		maxPlayersSlider.addChangeListener(this);
		this.add(maxPlayersSlider);
		maxPlayersSlider.setBounds(25, 140, 315, 35);
		
		this.add(remoteGameLabel);
		remoteGameLabel.setBounds(5, 175, 140, 20);
		
		this.add(remoteGameBox);
		remoteGameBox.setBounds(145, 175, 20, 20);
		
		expandButton.addActionListener(this);
		this.add(expandButton);
		expandButton.setBounds(5, 195, 335, 35);
		
		collapseButton.addActionListener(this);
		collapseButton.setBounds(5, 320, 335, 35);
		
		backButton.addActionListener(this);
		backButton.setDestinationPanel(PanelRegistry.getInstance().lookUpPanel(MainMenuPanel.PANEL_NAME));
		this.add(backButton);
		backButton.setBounds(5, 360, 165, 55);
		
		startButton.addActionListener(this);
		startButton.setDestinationPanel(PanelRegistry.getInstance().lookUpPanel(GameLobbyPanel.PANEL_NAME));
		this.add(startButton);
		startButton.setBounds(175, 360, 165, 55);
		
		customOptionsPanel.setBounds(0, 195, 350, 250);
	}

	@Override
	public void paintComponent(Graphics g){  
		super.paintComponent(g);
		g.drawImage(BACKGROUND_IMAGE, 0, 0, getWidth(), getHeight(), this);  
	}

	@Override
	public void stateChanged(ChangeEvent event) {
		if(event.getSource().equals(maxPlayersSlider)){
			maxPlayersSelectedField.setText(Integer.toString(maxPlayersSlider.getValue()));
		}
	}
	
	public void setLobbyGameEventListener(
			ILobbyGameEventListener lobbyGameEventListener) {
		this.lobbyGameEventListener = lobbyGameEventListener;
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		if (event.getSource().equals(expandButton)){
			this.add(customOptionsPanel);
			this.remove(expandButton);
			this.add(collapseButton);
			this.repaint();
		}
		else if (event.getSource().equals(collapseButton)) {
			this.remove(customOptionsPanel);
			this.remove(collapseButton);
			this.add(expandButton);
			this.repaint();
		}
		else if (event.getSource().equals(startButton)){
			if (remoteGameBox.isSelected()){
				startNewRemoteGame();
			}
			else {
				startNewLocalGame();
			}
		}
		else if (event.getSource().equals(backButton)){
			parentFrame.switchPanel(((INavigationButton)event.getSource()).getDestinationPanel());
		}
	}
	
	private void startNewRemoteGame(){
		if (!parentFrame.isLoggedIn()){
			parentFrame.waitForLogin();
			parentFrame.getLobbyCommandFactory().getLogin().login(null);
		}
		while(parentFrame.isWaitingForLoginResponse()){
			try {
				Thread.sleep(100);
			}
			catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (parentFrame.isLoggedIn()){
		parentFrame.getGameCommandFactory().getJoinGame().setPlayerName(
				((SettingsPanel)PanelRegistry.getInstance().lookUpPanel(SettingsPanel.PANEL_NAME)).getPlayerName());
		parentFrame.getLobbyCommandFactory().getCreateGame().createGame(
				gameNameTextField.getText(),
				(Mode)gameTypeComboBox.getSelectedItem(),
				maxPlayersSlider.getValue(),
				customOptionsPanel.getNormalBubblesCount(),
				customOptionsPanel.getGhostBubblesEnabled(),
				customOptionsPanel.getRainbowBubblesEnabled(),
				customOptionsPanel.getBlazingBubblesEnabled(),
				customOptionsPanel.getGravityEnabled(),
				customOptionsPanel.getWindEnabled(),
				customOptionsPanel.getFlippedFieldEnabled(),
				customOptionsPanel.getTeamsEnabled());
		int teamSize = customOptionsPanel.getTeamsEnabled() ? 2 : 1;
		((GameLobbyPanel)PanelRegistry.getInstance().lookUpPanel(GameLobbyPanel.PANEL_NAME)).gameJoined(
				maxPlayersSlider.getValue() / teamSize, teamSize);
		}
		else {
			// TODO: could not log in, throw error message
		}
	}

	private void startNewLocalGame(){
		ConfigReader configReader = new ConfigReader();
		try {
			configReader.initializeConfig("moltencore/server.ini");
		}
		catch (ConfigReaderException e1) {
			e1.printStackTrace();
		}
		
		Settings settings = new Settings(
				(Mode)gameTypeComboBox.getSelectedItem(),
				gameNameTextField.getText(),
				maxPlayersSlider.getValue(),
				customOptionsPanel.getTeamsEnabled() ? 2 : 1,
				3,
				customOptionsPanel.getGravityEnabled(),
				customOptionsPanel.getWindEnabled(),
				customOptionsPanel.getNormalBubblesCount(),
				false,
				Config.getInstance().getPushCount(),
				Config.getInstance().getOrdinaryBubbleProbability(),
				Config.getInstance().getRainbowBubbleProbability(),
				Config.getInstance().getGhostBubbleProbability(),
				Config.getInstance().getBlazingBubbleProbability()
					);
		
		lobbyGameEventListener.createLocalGame(settings);
		
			int teamSize = customOptionsPanel.getTeamsEnabled() ? 2 : 1;
		((GameLobbyPanel)PanelRegistry.getInstance().lookUpPanel(GameLobbyPanel.PANEL_NAME)).gameJoined(
				maxPlayersSlider.getValue() / teamSize, teamSize);
	}
}